const
  args = process.argv
  fs = require('fs')
  path = require('path')
  exec = require('child_process').exec
  ujs = require('uglify-js')
  babel = require('babel-core')
  rollup = require('rollup')
  sass = require('node-sass')
  riot = require('riot')
  md5 = require('md5-file')
  bs = require('browser-sync').create()
  chokidar = require('chokidar')
  opts = {
    // 静态目录
    'static': 'static'
  }
  fn = {
    opt: name => {
      return args.indexOf(`--${name}`) !== -1 ?
        args[args.indexOf(`--${name}`)+1] : null;
    }
  }
  fg = {
    Black: "\x1b[30m",
    Red: "\x1b[31m",
    Green: "\x1b[32m",
    Yellow: "\x1b[33m",
    Blue: "\x1b[34m",
    Magenta: "\x1b[35m",
    Cyan: "\x1b[36m",
    White: "\x1b[37m",
    Crimson: "\x1b[38m"
  }
  mkdirSync = path => {
    try {
      fs.mkdirSync(path)
    } catch(e) {
      if (e.code != 'EEXIST') throw e
    }
  }
  buildSass = (name, style) => {
    let base = path.join('project', name)
    return new Promise((rs,rj) => {
      sass.render({
        file: path.join(base, 'sass', `${style}.sass`),
        outputStyle: 'compressed'
      }, (err, result) => {
        if(err) throw err
        fs.writeFile(path.join(base, opts.static, 'css', `${style}.min.css`),
        result.css, err => {
          if(err) throw err
          console.log(fg.Green, 'sass编译成功! ', fg.White)
          rs()
        })
      })
    })
  }
  buildMain = (name) => {
    let base = path.join('project', name)
    fs.writeFile(path.join(base, opts.static, 'js', 'main.min.js'),
    ujs.minify(path.join(base, opts.static, 'js', 'main.js')).code, err => {
      if(err) throw err
      console.log(fg.Green, 'main.js编译成功! ', fg.White)
    })
  }
  mkMd5 = (name, style) => {
    let base = path.join('project', name)
    fs.readdir(path.join(base, 'tags'), (err, files) => {
      let
        tags = {}
        css = path.join(base, opts.static, 'css', `${style}.min.css`)
        cssMd5 = md5.sync(css)
        main = path.join(base, opts.static, 'js', `main.min.js`)
        mainMd5 = md5.sync(main)
      if(err) throw err
      files.forEach(f => {
        let
          item = path.join(base, 'tags', f),
          v
        if(!fs.lstatSync(item).isFile()) return
        v = md5.sync(item)
        tags[f.split('.')[0]] = `${opts.static}/tags/${f.replace('tag', 'js')}?v=${v}`
      })
      fs.readFile(path.join(base, opts.static, `${name}.json`), 'utf8', (err, data) => {
        if(err) throw err
        let json = JSON.parse(data)
        json.tags = tags
        json.styles[style] = `${opts.static}/css/${style}.min.css?v=${cssMd5}`
        json.main = `${opts.static}/js/main.min.js?v=${mainMd5}`
        fs.writeFile(path.join(base, opts.static, `${name}.json`),
          JSON.stringify(json), err => {
          if(err) throw err
          console.log(fg.Green, 'md5版本写入成功! ', fg.White)
        })
      })
    })
  }


// 观察项目 --dev project --name 项目名称
if(fn.opt('dev')){
  let
  name = fn.opt('dev')
  base = path.join('project', name)
  style = fn.opt('style') || 'default'
  modifiedFiles = []
  console.log(fg.Yellow, `开始开发项目${name}...`, fg.White)
  // sass
  fs.watchFile(path.join(base, 'sass', `${style}.sass`), cur => {
    buildSass(name, style)
  })
  // riot
  exec('riot -w '+path.join(base, 'tags')+' '+
                  path.join(base, opts.static, 'tags'))
  chokidar.watch(path.join(base, 'tags'))
  .on('change', f => {
    mkMd5(name, style)
  })
  // main
  chokidar.watch(path.join(base, opts.static, 'js', 'main.js'))
  .on('change', f => {
    buildMain(name)
    mkMd5(name, style)
  })
  // web
  bs.init({
    server: path.join(base),
    ui: false,
    notify: false,
    files: [
      path.join(base, 'static/'),
      path.join(base, 'index.html')
    ]
  })
}

// 编译项目 --build project --name 项目名称 --style 样式风格(默认 default)
if(fn.opt('build') === 'project' && fn.opt('name')){
  let
    name = fn.opt('name')
    style = fn.opt('style') || 'default'
    base = path.join('project', name)
  console.log(fg.Yellow, `编译项目${name}...`, fg.White)
  // sass
  let sassPromise = buildSass(name, style)

  // riot
  let riotPromise = new Promise((rs,rj) => {
    sassPromise.then(() => {
      exec('riot '+path.join(base, 'tags')+' '+
                   path.join(base, opts.static, 'tags'),
      err => {
        if(err) throw err
        console.log(fg.Green, 'riot编译成功! ', fg.White)
        rs()
      })
    })
  })

  // main.js
  buildMain(name)

  // md5 -> json
  riotPromise.then(() => {
    mkMd5(name, style)
  })
}


// 创建新项目 --create project --name 项目名称
if(fn.opt('create') === 'project' && fn.opt('name')){
  let
   name = fn.opt('name')
   base = path.join('project', name)
   tpl = fs.readFileSync(path.join('riot', 'bootstrap.html'), 'utf-8')
  console.log(fg.Yellow, `开始创建项目${name}...`)
  mkdirSync(base)
  tpl = tpl.replace(/@\{app\}/g, name)
  tpl = tpl.replace(/@\{static\}/g, opts.static)
  fs.writeFile(path.join(base, 'index.html'), tpl, err => {
    if(err) throw err
  })
  mkdirSync(path.join(base, 'sass'))
  fs.writeFile(path.join(base, 'sass', 'default.sass'), `
@import "../../../sass/normalize"
@import "../../../sass/mixin"`, err => {
    if(err) throw err
  })
  mkdirSync(path.join(base, 'tags'))
  fs.writeFile(path.join(base, 'tags', 'index.tag'), `
  <${name}-index>
    <h1>Hello World!</h1>
  </${name}-index>
  `, err => {
    if(err) throw err
  })
  mkdirSync(path.join(base, opts.static))
  fs.writeFile(path.join(base, opts.static, `${name}.json`), JSON.stringify({
    "lang": { "cn": {} },
    "styles": {},
    "tags": {}
  }), err => {
    if(err) throw err
  })
  mkdirSync(path.join(base, opts.static, 'css'))
  mkdirSync(path.join(base, opts.static, 'img'))
  mkdirSync(path.join(base, opts.static, 'js'))
  for(let f of ['core.min.js', 'riot.min.js', 'promise.min.js']){
    fs.createReadStream(path.join('dist', f)).pipe(
      fs.createWriteStream(path.join(base, opts.static, 'js', f))
    )
  }
  fs.writeFile(path.join(base, opts.static, 'js', 'main.js'), `
  var resources = ['${opts.static}/js/riot.min.js'];
  if(pip.ie() && pip.ie() < 9){
    alert('请升级您的浏览器.');
  }
  if('Promise' in window === false){
    resources.push('${opts.static}/js/promise.min.js');
  }
  pip.load(resources).on('done', function(){
    var app = new RiotApp({
      id: '${name}',
      version: '1.0',
      json: '${opts.static}/${name}.json',
      preload: null,
      debug: true
    });
  });
  `, err => {
    if(err) throw err
  })
  mkdirSync(path.join(base, opts.static, 'tags'))
  console.log(fg.Green, '成功! ', fg.White)
  // 需要先编译一次
  exec(`node ./cmd.js --build project --name ${name}`, err => {
    if(err) throw err
  })
}


if(fn.opt('build') === 'riot'){
  let
    version = fn.opt('v') || '3.0.7'
    files = [`${version}.js`, 'app.js']
  console.log(fg.Yellow, '开始编译riot核心文件...')
  if(fn.opt('route')){
    files.push('route.js')
  }
  files = files.map(f => {
    return f = 'riot/' + f
  });
  fs.writeFile('dist/riot.min.js', ujs.minify(files).code, err => {
    if(err) throw err
    console.log(fg.Green, '成功! ', fg.White)
  })
}


if(fn.opt('build') === 'modules'){
  console.log(fg.Yellow, '开始编译modules文件...')
  fs.readdir('modules/', (err, files) => {
    if(err) throw err;
    files.forEach(f => {
      let fname = f.split('.').slice(0,-1).join('.')
      fs.writeFile(
        `dist/${fname}.min.js`,
        ujs.minify('modules/' + f).code, err => {
          if(err) throw err
          console.log(fg.Green, `${fname} 成功!`, fg.White)
      })
    })
  });
}

if(fn.opt('build') === 'core'){

  let cache

  console.log(fg.Yellow, '开始编译core.es.js文件...')

  rollup.rollup({
    entry: 'bootstrap/core.es6.js',
    cache: cache
  })
  .then(bundle => {

    let result = bundle.generate({
      format: 'umd',
      moduleName: 'pip'
    }), code

    cache = bundle

    code = babel.transform(result.code, {
      presets: ['es2015-script']
    }).code

    code = ujs.minify(code, {
      fromString: true
    })

    fs.writeFile('dist/core.min.js', code.code, err => {
      if(err) throw err
      console.log(fg.Green, '成功! ', fg.White)
    })

  })

}
